﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Plugins;
using Plugins.Core;
using StockAccessors;
using StockAnalyst2.Plugins.Visualization.Realtime;
using Utils;
using StockModel;

namespace StockAnalyst2.Plugins.Engine
{
	internal class PluginSystem
	{
		#region Attributes

		private IDataBaseClient _dbClient;
		private QuotationDataSource _quotationDataSource;
		private ExchangeMarketDataSource _exchangeMarketDataSource;
		private PluginDetector _detector;
		private PluginActivator _activator;
		private PluginLoader _loader;

		#endregion

		#region Properties

		public ObservableCollection<IStrategyPlugin> Plugins { get; private set; }

		#endregion

		#region Events

		public event EventHandler<PluginAttachRequestedEventArgs> PluginAttachRequested;

		#endregion

		#region Public Methods

		public PluginSystem()
		{
			this.Plugins = new ObservableCollection<IStrategyPlugin>();
		}

		public void Initialize(IDataBaseClient dbClient, QuotationDataSource quotationDataSource, ExchangeMarketDataSource exchangeMarketDataSource, RawStockDataSource rawStockDataSource, ObservableCollection2<StockGroup> groups, IOrderExecutor executor, IStockDataAccessorInformation accessorInformation)
		{
			_dbClient = dbClient;
			_quotationDataSource = quotationDataSource;
			_exchangeMarketDataSource = exchangeMarketDataSource;

			_detector = new PluginDetector();
			_activator = new PluginActivator(_dbClient, _quotationDataSource, _exchangeMarketDataSource, rawStockDataSource, groups, executor, accessorInformation);
			_loader = new PluginLoader();
			_loader.PluginAttachRequested += this.Loader_PluginAttachRequested; // Local object

			IEnumerable<Type> pluginTypes = _detector.FindPlugins();
			IEnumerable<IStrategyPlugin> plugins = _activator.InstantiatePlugins(pluginTypes);
			_loader.Load(plugins);
		}

		public void LoadRealtimePlugins(RealtimePluginViewerVM viewer)
		{
			foreach (IStrategyPlugin plugin in this.Plugins)
			{
				if (plugin.SupportsRealtime)
				{
					viewer.Plugins.Add(plugin);
				}
			}
		}

		protected virtual void OnPluginAttachRequested(PluginAttachRequestedEventArgs e)
		{
			if (this.PluginAttachRequested != null)
			{
				this.Plugins.Add(e.Plugin);
				this.PluginAttachRequested(this, e);
			}
		}

		#endregion

		#region Event Handlers

		private void Loader_PluginAttachRequested(object sender, PluginAttachRequestedEventArgs e)
		{
			this.OnPluginAttachRequested(e);
		}
			   
		#endregion
	}
}
